perm filename GILEYE.SAI[SYS,HE]1 blob sn#004257 filedate 1972-08-25 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00014 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00003 00002	BEGIN "GILEYE" 
 00007 00003	PROCEDURE FINDIMAG(INTEGER BKGR,INT,SEARCH REAL TOLERREAL ARRAY DIRD)
 00010 00004	    SIMPLE PROCEDURE BOUND
 00013 00005	PROCEDURE CORNFIT
 00017 00006	SIMPLE PROCEDURE CNORML
 00021 00007	    MERR←.5
 00025 00008	PROCEDURE COLT(REAL TOLER REAL ARRAY DIRD)
 00028 00009	    IF DIRD[8]=1 THEN
 00030 00010	    DEFINE TURNCORNER="IF   (X=XFIN)∧(Y=YFIN)
 00033 00011	    ⊃ Run around the perimeter of the window
 00036 00012	
 00039 00013	SIMPLE PROCEDURE SRCHIMAG(INTEGER BKGR,INT,SEARCH REAL TOLER REAL ARRAY DIRD)
 00044 00014	PROCEDURE TESTIT
 00050 ENDMK
⊗;
BEGIN "GILEYE" 
REQUIRE "PREAMB.SAI[SYS,HE]" SOURCE_FILE;
REQUIRE "HELIB[1,3]" LIBRARY;
REQUIRE "DPYSUB.HDR[SYS,HE]" SOURCE_FILE;
REQUIRE -1 NEW_ITEMS;

INTEGER REQUEST,EXFLAG,DUMMY,MESS,MINI,MAXI,SCAL;
INTEGER ARRAY TVBUF[1:325],DPYBUF[1:2000],HIST[-1:16];

EXTERNAL INTEGER PROCEDURE GIOWD(INTEGER ARRAY BUF);
EXTERNAL PROCEDURE INTPNT;
EXTERNAL INTEGER TVWORD;

comment to run without PREAMB the following declarations should be added here;
comment	BOOLEAN DIS_EYE,DEB_EYE,TYP_EYE;
comment REAL ARRAY DIR_EYE[0:10,1:8];
comment INTEGER ARRAY LOOK_AT[1:8];

DEFINE ⊃="COMMENT";
DEFINE CRLF="&'15&'12";  DEFINE YES="INCHWL=""Y""";
DEFINE WAIT="IF DEB_EYE THEN BEGIN OUTSTR(""...TYPE Y TO CONTINUE...""CRLF);
             IF INCHWL=""Y"" THEN; END";
DEFINE WINDOW="X←0 STEP 1 UNTIL LOOK_AT[4]-1 DO
	       FOR Y←0 STEP 1 UNTIL LOOK_AT[5]-1";

REQUIRE "TVSER.SAI[SYS,HE]" SOURCE_FILE;

SIMPLE PROCEDURE DISPLAY;
 ⊃ Display the TV buffer;
  BEGIN INTEGER X,Y;
    EXTERNAL INTEGER PROCEDURE GETPNT(INTEGER X,Y);
    IF ¬DIS_EYE THEN RETURN;
    DPYTYP(-200,12,1); DPYSET(DPYBUF);
    DPYBRT(5); DPYBIG(2);

    IF DEB_EYE THEN BEGIN
    AIVECT(-400,0); RVECT(0,320);
    FOR X←0 STEP 1 UNTIL 16 DO BEGIN
	RVECT(-10,0); RIVECT(10,-20); END;
    FOR X←0 STEP 1 UNTIL 3 DO BEGIN
	AIVECT(-430,100*X); DPYSST(CVS(5*X)); END;
    AIVECT(-500,380); DPYSST("CLIPS");
    AIVECT(-400,0); RVECT(HIST[0]/(SCAL↑2),0);
    FOR X←0 STEP 1 UNTIL 14 DO BEGIN
	RVECT(0,20); RVECT((HIST[X+1]-HIST[X])/(SCAL↑2),0); END;
    RVECT(0,20); RVECT(-HIST[15]/(SCAL↑2),0);
    AIVECT(-500,40*(7-LOOK_AT[7])); RVECT(60,0);
    AIVECT(-500,40*(8-LOOK_AT[6])); RVECT(60,0);

		    END;
    AIVECT(60,380); DPYSST("SCAL=1:"&CVS(SCAL)); DPYBIG(1);
    FOR X←0 STEP SCAL UNTIL LOOK_AT[4]-1 DO
    FOR Y←0 STEP SCAL UNTIL LOOK_AT[5]-1 DO BEGIN
    AIVECT(20*(X DIV SCAL),340-20*(Y DIV SCAL)); DPYSST(CVS(GETPNT(X,Y))); END;
    SETFORMAT(8,4);
    AIVECT(-500,-50); DPYSST("LOOK_AT");
    FOR X←1 STEP 1 UNTIL 8 DO DPYSST(CVS(LOOK_AT[X]));
    DPYOUT(1); SETFORMAT(0,7);
  END"DISPLAY";
PROCEDURE FINDIMAG(INTEGER BKGR,INT,SEARCH; REAL TOLER;REAL ARRAY DIRD);
  BEGIN "FINDIMAG"
	INTEGER DX,DY,DUM,J,N,TRN,X,Y,XFIN,YFIN,ULEVEL,DLEVEL,WIDTH,HIGHT,
		SGN,FEATS,MATS,MAXDIM,MINDIM;
	INTEGER ARRAY WORK[0:LOOK_AT[4],0:LOOK_AT[5]],
		      EDGE[1:2*(LOOK_AT[4]+LOOK_AT[5]),1:3],SLEVEL[0:10];
  	REAL ARRAY DIRC[1:4];
	LABEL FOL,BACK1,BACK2,BACK3,BACK4,BACK,BACK0,RECNTR,FIN;
	BOOLEAN HAT;
        EXTERNAL INTEGER PROCEDURE GETPNT(INTEGER X,Y);

        INTEGER PROCEDURE STR(INTEGER X,XBAR);
	        RETURN(IF X≥XBAR THEN 1 ELSE IF X≤-XBAR THEN -1 ELSE 0);   

PROCEDURE SLICE(INTEGER BKGR);
  BEGIN INTEGER ARRAY HIST1[0:15];
	INTEGER I,J,BAR,MAX;
	EXTERNAL PROCEDURE DPYCLR;
    HISTO;
    IF LOOK_AT[6]=LOOK_AT[7] THEN BEGIN
    OUTSTR("SLICE-FAILED: UNIFORM INTENSITY IN WINDOW (CLIPS="&
	   CVS(LOOK_AT[6])&")"CRLF);
    EXFLAG←3; RETURN; END;

    ⊃ Find the maxima;
    BAR←(MINDIM↑2)/16; J←0; HIST[-1]←HIST[16]←0;
    FOR I←0 STEP 1 UNTIL 15 DO  
    IF   (HIST[I]≥BAR)∧(HIST[I]≥HIST[I-1])∧(HIST[I]>HIST[I+1])
    THEN BEGIN HIST1[I]←1; J←J+1; 
	       IF   J>1 
	       THEN BEGIN SLEVEL[J-1]←(MAX+I) DIV 2; MAX←I END
	       ELSE MAX←I; END;
    SLEVEL[0]←J-1;

    IF   SLEVEL[0]<1
    THEN BEGIN OUTSTR("SLICE-FAILED: ONLY ONE MAX FOUND"CRLF); EXFLAG←3; END
    ELSE IF BKGR≠0 THEN BEGIN
	 IF BKGR<0 THEN SLEVEL[1]←SLEVEL[SLEVEL[0]];
	 SLEVEL[0]←1;   END;

    IF DEB_EYE THEN BEGIN  DPYCLR;
    FOR I←0 STEP 1 UNTIL 15 DO
    OUTSTR(CVS(I)&"	"&CVS(HIST[I])&"	"&CVS(HIST1[I])CRLF); 
    OUTSTR(CVS(SLEVEL[0])&" SLEVELS:");
    FOR I←1 STEP 1 UNTIL SLEVEL[0] DO OUTSTR("  "&CVS(SLEVEL[I]));
    OUTSTR(""CRLF); END;
    WAIT;

  END "SLICE";

    SIMPLE PROCEDURE BOUND;
     BEGIN INTEGER I;
       IF ¬HAT THEN BEGIN X←X+DX; Y←Y+DY; END ELSE HAT←FALSE;
       DLEVEL←0; ULEVEL←16;
       FOR I← 1 STEP 1 UNTIL SLEVEL[0] DO
           IF   GETPNT(X,Y)<(ULEVEL←SLEVEL[I])
	   THEN DONE
    	   ELSE BEGIN DLEVEL←ULEVEL; ULEVEL←16; END;
       IF DEB_EYE THEN
	  OUTSTR("BOUND: DLEVEL="&CVS(DLEVEL)&"  ULEVEL="&CVS(ULEVEL)CRLF);
     END "BOUND";

    SIMPLE PROCEDURE DISP_EDGE;
      BEGIN INTEGER L;
        IF (¬DIS_EYE)∨(N<2) THEN RETURN;
        AIVECT(10+20*EDGE[1,1]/SCAL,350-20*EDGE[1,2]/SCAL);
        FOR L←2 STEP 1 UNTIL N DO
        RVECT(20*(EDGE[L,1]-EDGE[L-1,1])/SCAL,
             -20*(EDGE[L,2]-EDGE[L-1,2])/SCAL);
        DPYOUT(1);
      END"DISP_EDGE";

    SIMPLE PROCEDURE PRUNE;
      ⊃ Prune loops and branches from the edge points;
      BEGIN "PRUNE" 
        INTEGER J,K,L,LUP;

        LUP←0;
        FOR J←1 STEP 1 UNTIL N DO BEGIN
            IF EDGE[J,3]=2 THEN BEGIN
               K←J-2; LUP←1;
               WHILE (EDGE[K,1]≠EDGE[J,1])∨(EDGE[K,2]≠EDGE[J,2]) DO K←K-1;
               FOR L←K+1 STEP 1 UNTIL J-1 DO EDGE[L,3]←2; END; END;

        IF LUP=1 THEN BEGIN
           K←1;
           FOR L←1 STEP 1 UNTIL N DO 
               IF EDGE[L,3]=1 THEN BEGIN
                  EDGE[K,1]←EDGE[L,1];
                  EDGE[K,2]←EDGE[L,2]; K←K+1; END;
           N←K-1;     END;

        DISP_EDGE;
      END "PRUNE";

    SIMPLE PROCEDURE DISP_DIR;
      BEGIN INTEGER I; IF ¬DIS_EYE THEN RETURN;
        AIVECT(-500,-50-J*20); DPYBRT(3); SETFORMAT(8,4); DPYSST("DIR_EYE");
        FOR I←1 STEP 1 UNTIL 8 DO DPYSST(CVG(DIR_EYE[J,I])); DPYOUT(1); 
        DPYBRT(5); SETFORMAT(0,7);
      END"DISP_DIR";
PROCEDURE CORNFIT;
  BEGIN "CORNFIT" REAL X,Y,MX,MY,SIGX,SIGY,SIGXY,A,B,C,A1,A2,B1,B2,C1,C2,
             AM1,AM2,BM1,BM2,CM1,CM2,ERR,TERR,MERR,G,U1,U2,
	     ERR1,ERR2,D1,D2,E1,E2,XIC,YIC,XIB,YIB,XID,YID;
	INTEGER I,K,M,J;
	LABEL SH;
	REAL ARRAY SX,SY,SQX,SQY,SXY[-1:1];
	FORTRAN REAL PROCEDURE SQRT(REAL X);

  DEFINE COUNT(K)="
    X←EDGE[I,1];  Y←EDGE[I,2];
    SX[K]←SX[K]+K*X;    SY[K]←SY[K]+K*Y;
    SQX[K]←SQX[K]+K*X↑2;  SQY[K]←SQY[K]+K*Y↑2;  SXY[K]←SXY[K]+K*X*Y; ";

  DEFINE RMS(K)="
    MX←SX[K]/M;  MY←SY[K]/M;
    SIGX←SQX[K]/M-MX↑2;   SIGY←SQY[K]/M-MY↑2;   SIGXY←SXY[K]/M-MX*MY;
    IF   ABS(SIGXY)<.0001
    THEN IF   SIGX>SIGY
         THEN BEGIN A←0; B←1; C←-MY; ERR←SIGY; END
	 ELSE BEGIN A←1; B←0; C←-MX; ERR←SIGX; END
    ELSE BEGIN
    G←(SIGX-SIGY)/(2*SIGXY); U2←SQRT(1+G↑2);
    U1←-G+U2; U2←-G-U2; 
    D1←1/SQRT(1+U1↑2); D2←1/SQRT(1+U2↑2); E1←U1*D1; E2←U2*D2;
    ERR1←D1↑2*SIGX+E1↑2*SIGY+2*D1*E1*SIGXY;
    ERR2←D2↑2*SIGX+E2↑2*SIGY+2*D2*E2*SIGXY;
    IF   ERR1<ERR2
    THEN BEGIN ERR←ERR1; A←D1; B←E1; C←-(A*MX+B*MY); END
    ELSE BEGIN ERR←ERR2; A←D2; B←E2; C←-(A*MX+B*MY); END;
       END;";

SIMPLE PROCEDURE CUT(REAL X1,X2,Y1,Y2,A,B,C;REFERENCE REAL D1,D2,E1,E2);
  BEGIN IF X1>X2 THEN X1↔X2; IF Y1>Y2 THEN Y1↔Y2;
    IF   A=0
    THEN BEGIN D1←X1; D2←X2; E1←E2←-C/B; END
    ELSE IF B=0 
	 THEN BEGIN E1←Y1; E2←Y2; D1←D2←-C/A; END
	 ELSE CASE (IF (E1←-(C+A*X1)/B)≤Y1 THEN 0 ELSE IF E1≤Y2 THEN 1 ELSE 2)+
	         3*(IF (E2←-(C+A*X2)/B)≤Y1 THEN 0 ELSE IF E2≤Y2 THEN 1 ELSE 2)
  	      OF BEGIN
 	BEGIN ⊃ 0;							END;
	BEGIN ⊃ 1; D1←X1; E2←Y1; D2←-(C+B*E2)/A;			END;
	BEGIN ⊃ 2; E1←Y2; D1←-(C+B*E1)/A; E2←Y1; D2←-(C+B*E2)/A;	END;
	BEGIN ⊃ 3; E1←Y1; D1←-(C+B*E1)/A; D2←X2;			END;
	BEGIN ⊃ 4; D1←X1; D2←X2;					END;
	BEGIN ⊃ 5; E1←Y2; D1←-(C+B*E1)/A; D2←X2;			END;
	BEGIN ⊃ 6; E1←Y1; D1←-(C+B*E1)/A; E2←Y2; D2←-(C+B*E2)/A;	END;
	BEGIN ⊃ 7; D1←X1; E2←Y2; D2←-(C+B*E2)/A;			END;
	BEGIN ⊃ 8;							END;
		 END;
  END "CUT";
SIMPLE PROCEDURE CNORML;
  BEGIN REAL D;
    D←SQRT((XIB-XIC)↑2+(YIB-YIC)↑2);
    DIR_EYE[J,1]←(XIB-XIC)/D; DIR_EYE[J,2]←(YIB-YIC)/D;
    D←SQRT((XID-XIC)↑2+(YID-YIC)↑2);
    DIR_EYE[J,3]←(XID-XIC)/D; DIR_EYE[J,4]←(YID-YIC)/D;
    IF (DIR_EYE[J,1]*DIR_EYE[J,4]-DIR_EYE[J,2]*DIR_EYE[J,3])<0
    THEN BEGIN DIR_EYE[J,1]↔DIR_EYE[J,3]; DIR_EYE[J,2]↔DIR_EYE[J,4];
	 DIR_EYE[J,8]←1; END
    ELSE DIR_EYE[J,8]←0;
    DIR_EYE[J,5]←XIC; DIR_EYE[J,6]←YIC; DIR_EYE[J,7]←0;
  END "CNORML";

SIMPLE PROCEDURE LNORML;
  BEGIN "LNORML"
	REAL D;
    D←SQRT((XIB-XID)↑2+(YIB-YID)↑2);
    DIR_EYE[J,1]←(XIB-XID)/D; DIR_EYE[J,2]←(YIB-YID)/D;
    IF   DIR_EYE[J,1]=0
    THEN DIR_EYE[J,2]←-ABS(DIR_EYE[J,2])
    ELSE IF   DIR_EYE[J,1]>0
         THEN BEGIN DIR_EYE[J,1]←-DIR_EYE[J,1]; DIR_EYE[J,2]←-DIR_EYE[J,2]; END;
    DIR_EYE[J,3]←-DIR_EYE[J,1]; DIR_EYE[J,4]←-DIR_EYE[J,2];
    XIC←DIR_EYE[J,5]←(XIB+XID)/2; YIC←DIR_EYE[J,6]←(YIB+YID)/2;
    DIR_EYE[J,7]←1; DIR_EYE[J,8]←0;
  END "LNORML";

    J←DIR_EYE[0,1];
    FOR K←-1,1 DO SX[K]←SY[K]←SQX[K]←SQY[K]←SXY[K]←0;
    FOR I←1 STEP 1 UNTIL N DO BEGIN COUNT(1) END;
    M←N; RMS(1)
    IF ERR<.25 THEN BEGIN
       CUT(0,WIDTH-1,0,HIGHT-1,A,B,C,D1,D2,E1,E2);
       XIB←LOOK_AT[2]-(WIDTH DIV 2)+D1; YIB←LOOK_AT[3]-(HIGHT DIV 2)+E1;
       XID←LOOK_AT[2]-(WIDTH DIV 2)+D2; YID←LOOK_AT[3]-(HIGHT DIV 2)+E2;
       LNORML;
       OUTSTR("CORNFIT: LINE FOUND M.S.E="&CVG(ERR)CRLF);
       IF DEB_EYE THEN BEGIN
          OUTSTR("C=("&CVG(XIC)&CVG(YIC)&")"CRLF);
          OUTSTR("B=("&CVG(XIB)&CVG(YIB)&")");
          OUTSTR("D=("&CVG(XID)&CVG(YID)&")"CRLF); END;
       IF DIS_EYE THEN BEGIN 
          AIVECT(10+20*D1/SCAL,350-20*E1/SCAL);
          RVECT(20*(D2-D1)/SCAL,-20*(E2-E1)/SCAL);
          DPYOUT(1);   END;
       RETURN;      END;

    SX[1]↔SX[-1]; SY[1]↔SY[-1]; SQX[1]↔SQX[-1]; SQY[1]↔SQY[-1]; SXY[1]↔SXY[-1];
    FOR I←1  STEP 1 UNTIL 2 DO BEGIN
    COUNT(1); COUNT(-1);       END;
    MERR←.5;
    FOR I←3 STEP 1 UNTIL N-3 DO BEGIN 
	COUNT(1); M←I; RMS(1); TERR←M*ERR; A1←A; B1←B; C1←C;
 	COUNT(-1); M←N-I; RMS(-1); TERR←(TERR+M*ERR)/N; A2←A; B2←B; C2←C;
SH:	IF   TERR<MERR
	THEN BEGIN MERR←TERR; AM1←A1; BM1←B1; CM1←C1; 
			      AM2←A2; BM2←B2; CM2←C2; END; END;

    IF MERR=.5 THEN BEGIN
    OUTSTR("CORNFIT-FAILED: NO FIT"CRLF); DIR_EYE[J,7]←-1; RETURN;
		    END;
    IF   AM1=0  
    THEN BEGIN Y←-CM1/BM1; X←-(CM2+BM2*Y)/AM2; END
    ELSE IF   AM2=0
	 THEN BEGIN Y←-CM2/BM2; X←-(CM1+BM1*Y)/AM1; END
	 ELSE IF   BM1=0
	      THEN BEGIN X←-CM1/AM1; Y←-(CM2+AM2*X)/BM2; END
	      ELSE IF   BM2=0 
		   THEN BEGIN X←-CM2/AM2; Y←-(CM1+AM1*X)/BM1; END
		   ELSE BEGIN X←(BM1*CM2-BM2*CM1)/(AM1*BM2-AM2*BM1); 
			      Y←-(AM1*X+CM1)/BM1; END;
    IF   (X<1)∨(X>WIDTH-1)∨(Y<1)∨(Y>HIGHT-1)
    THEN BEGIN OUTSTR("CORNFIT-FAILED: CORNER IS OUT OF WINDOW"CRLF);
	       DIR_EYE[J,7]←-1; RETURN; END;
    XIC←LOOK_AT[2]-(WIDTH DIV 2)+X; YIC←LOOK_AT[3]-(HIGHT DIV 2)+Y;
    CUT(0,WIDTH-1,0,HIGHT-1,AM1,BM1,CM1,D1,A,E1,B);
    IF  ((D1-EDGE[1,1])↑2+(E1-EDGE[1,2])↑2)>
        ((A-EDGE[1,1])↑2+(B-EDGE[1,2])↑2)
    THEN BEGIN D1←A; E1←B; END;
    CUT(0,WIDTH-1,0,HIGHT-1,AM2,BM2,CM2,D2,A,E2,B);
    IF  ((D2-EDGE[N,1])↑2+(E2-EDGE[N,2])↑2)>
        ((A-EDGE[N,1])↑2+(B-EDGE[N,2])↑2)
    THEN BEGIN D2←A; E2←B; END;
    XIB←LOOK_AT[2]-(WIDTH DIV 2)+D1; YIB←LOOK_AT[3]-(HIGHT DIV 2)+E1;
    XID←LOOK_AT[2]-(WIDTH DIV 2)+D2; YID←LOOK_AT[3]-(HIGHT DIV 2)+E2;
    CNORML;
    OUTSTR("CORNFIT: CORNER FOUND M.S.E="&CVG(MERR)CRLF);
    IF DEB_EYE THEN BEGIN
       OUTSTR("C=("&CVG(XIC)&CVG(YIC)&")"CRLF);
       OUTSTR("B=("&CVG(XIB)&CVG(YIB)&")");
       OUTSTR("D=("&CVG(XID)&CVG(YID)&")"CRLF); END;

    ⊃ Display;

    IF DIS_EYE THEN BEGIN
    AIVECT(10+20*D1/SCAL,350-20*E1/SCAL);
    RVECT(20*(X-D1)/SCAL,-20*(Y-E1)/SCAL);
    RVECT(20*(D2-X)/SCAL,-20*(E2-Y)/SCAL);	
    DPYOUT(1);     END;

  END "CORNFIT";
PROCEDURE COLT(REAL TOLER; REAL ARRAY DIRD);
   BEGIN REAL ARRAY E[1:4];
	 INTEGER I,J,K;
	 REAL MINE;
	 STRING EES; 
	 LABEL MATCH,CMATCH,NMATCH,PMATCH;
    J←DIR_EYE[0,1];
    IF DEB_EYE THEN BEGIN OUTSTR("COLT: DIRD=(");
    FOR K←1 STEP 1 UNTIL 8 DO OUTSTR(CVG(DIRD[K])); OUTSTR(")"CRLF);
    OUTSTR("COLT: DIR_EYE=(");
    FOR K←1 STEP 1 UNTIL 8 DO OUTSTR(CVG(DIR_EYE[J,K])); OUTSTR(")"CRLF); END;
    E[1]←DIRD[1]*DIR_EYE[J,1]+DIRD[2]*DIR_EYE[J,2];
    E[2]←DIRD[3]*DIR_EYE[J,3]+DIRD[4]*DIR_EYE[J,4];
    E[3]←DIRD[1]*DIR_EYE[J,3]+DIRD[2]*DIR_EYE[J,4];
    E[4]←DIRD[3]*DIR_EYE[J,1]+DIRD[4]*DIR_EYE[J,2];
    EES←"E's=("&CVG(E[1])&CVG(E[2])&CVG(E[3])&CVG(E[4])&")";

    IF DIRD[8]=0 THEN BEGIN
     ⊃ Case 1: D and E are corners;
    IF (DIRD[7]=0)∧(DIR_EYE[J,7]=0) THEN BEGIN
       IF (E[1]>1-TOLER)∧(E[2]>1-TOLER) THEN GOTO MATCH;
       MINE←1;
       FOR K←1 STEP 1 UNTIL 4 DO 
       	   IF E[K]≤MINE THEN BEGIN MINE←E[K]; I←K; END;
       IF   MINE<-(1-TOLER)
       THEN BEGIN IF (I=1)∨(I=4) THEN I←1 ELSE I←2; GOTO CMATCH; END
       ELSE GOTO NMATCH;		  END;

    ⊃ Case 2: D and E are lines;
      IF   (DIRD[7]=1)∧(DIR_EYE[J,7]=1) 
      THEN IF   ABS(E[1])>1-TOLER
	   THEN GOTO MATCH ELSE GOTO NMATCH; 

    ⊃ Case 3: D is a corner and E is a line;
      IF (DIRD[7]=0)∧(DIR_EYE[J,7]=1) THEN BEGIN
	 IF ABS(E[1])>ABS(E[4]) THEN I←1 ELSE I←4;
	 IF   ABS(E[I])>(1-TOLER)
	 THEN BEGIN IF E[I]<-.5 THEN I←1 ELSE I←2; GOTO CMATCH; END
	 ELSE GOTO NMATCH;		   END;

    ⊃ Case 4: D is a line and E is a corner;
      IF (DIRD[7]=1)∧(DIR_EYE[J,7]=0) THEN BEGIN
	 IF ABS(E[1])>ABS(E[3]) THEN I←1 ELSE I←3;
	 IF   ABS(E[I])>(1-TOLER)
	 THEN BEGIN IF I=3 THEN I←2; GOTO CMATCH; END
	 ELSE GOTO NMATCH;		   END;
		      END;

    IF DIRD[8]=1 THEN
       IF   E[1]>1-TOLER
       THEN BEGIN I←1; GOTO PMATCH; END
       ELSE IF   E[3]>1-TOLER
	    THEN BEGIN I←2; GOTO PMATCH; END
	    ELSE GOTO NMATCH;

    IF DIRD[8]=2 THEN
       IF   E[2]>1-TOLER
       THEN BEGIN I←2; GOTO PMATCH; END
       ELSE IF   E[4]>1-TOLER
	    THEN BEGIN I←1; GOTO PMATCH; END
	    ELSE GOTO NMATCH;

    IF DIRD[8]=3 THEN
       IF   (E[1]>1-TOLER)∨(E[4]>1-TOLER)
       THEN BEGIN I←1; GOTO PMATCH; END
       ELSE IF   (E[3]>1-TOLER)∨(E[2]>1-TOLER)
	    THEN BEGIN I←2; GOTO PMATCH; END
	    ELSE GOTO NMATCH;

   NMATCH: OUTSTR("COLT-FAILED: NO MATCH "&EES CRLF); DIR_EYE[J,8]←-1;
	   EXFLAG←11; RETURN;
   CMATCH: OUTSTR("COLT: EDGE NO. "&CVS(I)&" C-MATCHED "&EES CRLF);
           DIR_EYE[J,8]←I; EXFLAG←13; RETURN;
   PMATCH: DIR_EYE[J,8]←I; RETURN;
    MATCH: DIR_EYE[J,8]←0;
  END "COLT";
    DEFINE TURNCORNER="IF   (X=XFIN)∧(Y=YFIN)
           	       THEN GOTO FIN
	   	       ELSE BEGIN  DX↔DY; DY←-DY; END;";

    DEFINE ADVANCE="IF   ((SGN←GETPNT(X+DX,Y+DY))≥DLEVEL)∧(SGN<ULEVEL)
		    THEN BEGIN X←X+DX; Y←Y+DY; END
                    ELSE IF ((BKGR≥0)∧(SGN≥ULEVEL))∨((BKGR<0)∧(SGN<DLEVEL))
		         THEN GOTO FOL
		         ELSE BOUND;";

    ⊃ Define the window;

	IF   LOOK_AT[4]>LOOK_AT[5]
	THEN BEGIN MINDIM←LOOK_AT[5]; MAXDIM←LOOK_AT[4]; END
	ELSE BEGIN MINDIM←LOOK_AT[4]; MAXDIM←LOOK_AT[5]; END;
	IF  (LOOK_AT[4]*LOOK_AT[5])>2916
	THEN BEGIN OUTSTR("FINDIMAG-FAILED: WINDOW TOO BIG FOR TVBUF (WIDTH="&
		          CVS(LOOK_AT[4])&"  HIGHT="&CVS(LOOK_AT[5])&")"CRLF);
	           EXFLAG←1; RETURN; END;
	IF   MINDIM<5
	THEN BEGIN OUTSTR("FINDIMAG-FAILED: WINDOW TOO NARROW (MINDIM="&
			  CVS(MINDIM)&")"CRLF);
	           EXFLAG←1; RETURN; END;
	WIDTH←LOOK_AT[4]; HIGHT←LOOK_AT[5]; SCAL←(MAXDIM-1) DIV 18+1;
        J←DIR_EYE[0,1]; IF TOLER>0 THEN ARRBLT(DIRC[1],DIRD[1],4);

    ⊃ Accomodate, read in the window, find SLEVEL and display;

  RECNTR: NEEDNEXT WHILE EXFLAG=0 DO BEGIN
	  SETCLIP; NEXT; INPUT; NEXT; SLICE(BKGR); DISPLAY; DONE; END;
	  IF EXFLAG≠0 THEN RETURN;
	  IF (TOLER>0)∧(DIS_EYE) THEN BEGIN
	  AIVECT(-150,200); RVECT(100*DIRD[1],-100*DIRD[2]); RIVECT(0,20); DPYSST("1");
	  AIVECT(-150,200); RVECT(100*DIRD[3],-100*DIRD[4]); RIVECT(0,20); DPYSST("2");
      	  DPYOUT(1); END;

    ⊃ Find the starting corner;
    
    IF (DIRC[1]+DIRC[2]/16)≥0 THEN Y←HIGHT-2 ELSE Y←1;
    IF (DIRC[2]-DIRC[1]/16)≥0 THEN X←1 ELSE X←WIDTH-2;
    XFIN←X; YFIN←Y; HAT←TRUE;
    IF DIS_EYE THEN BEGIN
    AIVECT(20*X/SCAL,340-20*Y/SCAL);
    RVECT(0,20); RVECT(20,0); RVECT(0,-20); RVECT(-20,0);
    DPYOUT(1); END;

    MATS←FEATS←0; GOTO BACK0;
    ⊃ Run around the perimeter of the window;

  BACK:  WAIT; X←EDGE[1,1]; Y←EDGE[1,2];
  BACK0: N←0; BEGIN INTEGER X,Y; FOR WINDOW DO WORK[X,Y]←0; END;
         IF   (Y=1)∧(X≠1)
         THEN BEGIN DX←-1; DY←0; BOUND; GOTO BACK4; END
         ELSE IF   X=WIDTH-2
	      THEN BEGIN DX←0; DY←-1; BOUND; GOTO BACK3; END
	      ELSE IF   Y=HIGHT-2
	           THEN BEGIN DX←1; DY←0; BOUND; GOTO BACK2; END
	           ELSE BEGIN DX←0; DY←1; BOUND; GOTO BACK1; END; 

  BACK1: WHILE Y<(HIGHT-2) DO BEGIN ADVANCE END; TURNCORNER;
  BACK2: WHILE X<(WIDTH-2) DO BEGIN ADVANCE END; TURNCORNER;
  BACK3: WHILE Y>1 DO BEGIN ADVANCE END; TURNCORNER; 
  BACK4: WHILE X>1 DO BEGIN ADVANCE END; TURNCORNER; GOTO BACK1;

    ⊃ Follow the edge;

  FOL : IF   WORK[X,Y]<2
        THEN BEGIN WORK[X,Y]←1+WORK[X,Y]; TRN←9;
             N←N+1; EDGE[N,1]←X; EDGE[N,2]←Y; EDGE[N,3]←WORK[X,Y]; END
        ELSE BEGIN OUTSTR("FINDIMAG: I AM IN A LOOP"CRLF); GOTO BACK; END;

        IF (X≠0)∧(X≠WIDTH-1)∧(Y≠0)∧(Y≠HIGHT-1) THEN BEGIN
	   WHILE (TRN≥0)∧(((SGN←GETPNT(X+DX,Y+DY))<DLEVEL)∨(SGN≥ULEVEL)) DO 
           BEGIN TRN←TRN-1; DUM←STR(DY+DX,1); DY←STR(DY-DX,1); DX←DUM; END;
           IF   TRN<0 
	   THEN BEGIN OUTSTR("FINDIMAG: SINGLE POINT"CRLF); GOTO BACK; END;
		      
           X←X+DX;Y←Y+DY; 
           IF   DX*DY=0
           THEN BEGIN DX←DX-DY; DY←DX+DY*2; END
           ELSE BEGIN DY↔DX; DX←-DX; END;
	   GOTO FOL;  				    END;

    DISP_EDGE;
    IF N<MINDIM DIV 2 THEN BEGIN 
       OUTSTR("FINDIMAG: FEW POINTS BEFORE PRUNING (N="&CVS(N)&")"CRLF);
       GOTO BACK;      END;
    PRUNE;
    IF N<MINDIM DIV 2 THEN BEGIN
       OUTSTR("FINDIMAG: FEW POINTS AFTER PRUNING (N="&CVS(N)&")"CRLF);
       GOTO BACK;      END;
    CORNFIT;
    IF DIR_EYE[J,7]=-1 THEN GOTO BACK;
    FEATS←FEATS+1;
    IF   (INT≠0)∧(DIR_EYE[J,7]=0)∧(DIRD[7]=0)∧
         (((DIR_EYE[J,8]=1)∧(((INT>0)∧(BKGR≥0))∨((INT<0)∧(BKGR<0))))
         ∨((DIR_EYE[J,8]=0)∧(((INT>0)∧(BKGR<0))∨((INT<0)∧(BKGR≥0))))) 
    THEN BEGIN OUTSTR("FIND_IMAGE: WRONG INTENSITY INSIDE CORNER"CRLF);
	 EXFLAG←9; GOTO BACK; END
    ELSE EXFLAG←0;
    IF (SEARCH≥0)∧((ABS(DIR_EYE[J,5]-LOOK_AT[2])>WIDTH/8)∨
                   (ABS(DIR_EYE[J,6]-LOOK_AT[3])>HIGHT/8)) THEN BEGIN
       LOOK_AT[2]←DIR_EYE[J,5]; LOOK_AT[3]←DIR_EYE[J,6];
       IF TOLER<0 THEN ARRBLT(DIRC[1],DIR_EYE[J,1],4);
       GOTO RECNTR; 						END; 
    IF   TOLER>0
    THEN BEGIN COLT(TOLER,DIRD);
         IF (SEARCH>0)∧(DIR_EYE[J,8]>0) THEN GOTO FIN;
         IF   (DIR_EYE[J,8]=0)∨((DIRD[8]>0)∧(DIR_EYE[J,8]>0))
         THEN MATS←MATS+1 
         ELSE GOTO BACK; END
    ELSE IF   (DIR_EYE[J,7]=1)∧(DIRD[7]=0)
	 THEN BEGIN EXFLAG←7;
	      IF SEARCH>0 THEN GOTO FIN ELSE GOTO BACK; END;

    DISP_DIR; DIR_EYE[0,1]←J←J+1; IF J+SEARCH≤0 THEN GOTO BACK;

    FIN: IF   FEATS=0
         THEN BEGIN OUTSTR("FINDIMAG-FAILED: NO FEATS FOUND "CRLF);
	      EXFLAG←5; END
         ELSE BEGIN OUTSTR("FINDIMAG: "&CVS(FEATS)&" FEATS FOUND"CRLF);
	      IF TOLER>0 THEN
	         IF   MATS=0
                 THEN OUTSTR("FINDIMAG-FAILED:" &"NO MATCHES FOUND"CRLF)
	         ELSE OUTSTR("FINDIMAG: "&CVS(MATS)&" MATCHES FOUND"CRLF);
	      END;
         WAIT;
 END "FINDIMAG";
SIMPLE PROCEDURE SRCHIMAG(INTEGER BKGR,INT,SEARCH; REAL TOLER; REAL ARRAY DIRD);
  BEGIN INTEGER K,LSB,RSB,FLB,LLB,HWIDTH,HHIGHT,XIC0,YIC0,HDIM,J,L;
	REAL F;
	LABEL MLINE,SLINE;

    DEFINE ADVANCE="LOOK_AT[2]←XIC0+J*HWIDTH; LOOK_AT[3]←YIC0+L*HHIGHT;
	             EXFLAG←0; FINDIMAG(BKGR,INT,1,TOLER,DIRD);
	             IF EXFLAG=0 THEN RETURN;
                     IF   TOLER>0 
		     THEN BEGIN IF EXFLAG=13 THEN GOTO MLINE; END
		     ELSE IF EXFLAG=7 THEN BEGIN K←1;
			     XIC0←DIR_EYE[1,5]; YIC0←DIR_EYE[1,6];
			     GOTO SLINE; END;";

    IF SEARCH≤0 THEN BEGIN FINDIMAG(BKGR,INT,SEARCH,TOLER,DIRD); RETURN; END;

    HWIDTH←LOOK_AT[4] DIV 2; HHIGHT←LOOK_AT[5] DIV 2; XIC0←LOOK_AT[2]; YIC0←LOOK_AT[3];
    IF (HDIM←HWIDTH)>HHIGHT THEN HDIM←HHIGHT;
    LSB←XIC0-SEARCH*HWIDTH; RSB←XIC0+SEARCH*HWIDTH;
    FLB←YIC0-SEARCH*HWIDTH; LLB←YIC0+SEARCH*HWIDTH;
    J←L←0; ADVANCE;

    ⊃ Search;

    FOR K←1 STEP 1 UNTIL SEARCH DO BEGIN
    L←-K; FOR J←-K   STEP 1  UNTIL K    DO BEGIN ADVANCE END;
    J←K;  FOR L←-K+1 STEP 1  UNTIL K    DO BEGIN ADVANCE END;
    L←K;  FOR J←K-1  STEP -1 UNTIL -K   DO BEGIN ADVANCE END;
    J←-K; FOR L←K-1  STEP -1 UNTIL -K+1 DO BEGIN ADVANCE END;
				   END;
    OUTSTR("SRCHIMAG-FAILED: NOTHING FOUND IN SEARCH SPACE"CRLF); RETURN;

    ⊃ Line Follower;

   MLINE: IF DIR_EYE[1,7]=1 THEN F←1 ELSE F←4/3;
          IF DIR_EYE[1,8]=1 THEN BEGIN
          LOOK_AT[2]←HDIM*DIR_EYE[1,1]*F+DIR_EYE[1,5];
          LOOK_AT[3]←HDIM*DIR_EYE[1,2]*F+DIR_EYE[1,6];
	                         END;
          IF DIR_EYE[1,8]=2 THEN BEGIN
          LOOK_AT[2]←HDIM*DIR_EYE[1,3]*F+DIR_EYE[1,5]; 
          LOOK_AT[3]←HDIM*DIR_EYE[1,4]*F+DIR_EYE[1,6];
	                  	 END;
          IF (LOOK_AT[2]≥LSB)∧(LOOK_AT[2]≤RSB)∧
	     (LOOK_AT[3]≥FLB)∧(LOOK_AT[3]≤LLB) 
          THEN BEGIN 
	       EXFLAG←0; FINDIMAG(BKGR,INT,1,TOLER,DIRD);
	       IF EXFLAG=0 THEN RETURN;
               IF EXFLAG=13 THEN GOTO MLINE;
	       END;
	  OUTSTR("SRCHIMAG-FAILED: PARTIAL MATCH FOLLOWED, NO FINDS"CRLF);
	  RETURN;

   SLINE: LOOK_AT[2]←HDIM*DIR_EYE[1,K]+DIR_EYE[1,5];
          LOOK_AT[3]←HDIM*DIR_EYE[1,K+1]+DIR_EYE[1,6];
          IF (LOOK_AT[2]≥LSB)∧(LOOK_AT[2]≤RSB)∧
	     (LOOK_AT[3]≥FLB)∧(LOOK_AT[3]≤LLB) 
          THEN BEGIN 
	       EXFLAG←0; FINDIMAG(BKGR,INT,1,TOLER,DIRD);
	       IF EXFLAG=0 THEN RETURN;
               IF EXFLAG=7 THEN GOTO SLINE; END;
	  IF   K=1 
	  THEN BEGIN K←3;
	       DIR_EYE[1,5]←XIC0; DIR_EYE[1,6]←YIC0; GOTO SLINE; END;
	  OUTSTR("SRCHIMAG-FAILED: LINE FOLLOWED, NO FINDS"CRLF);
  END "SRCHIMAG";
PROCEDURE TESTIT;
  BEGIN INTEGER BKGR,INT,SEARCH,PERS,REQUEST;
        REAL ARRAY DIRG[1:8];
	STRING COD;
	REAL TOLER;
	LABEL TIT,TES;
 	PERS←0; DIRG[7]←1;
  TIT: EXFLAG←0; DIR_EYE[0,1]←1;
       SETWINDOW; IF EXFLAG≠0 THEN GOTO TIT;

       OUTSTR("0-SHOW MEANING OF PARAMETER VALUES"CRLF);
       OUTSTR("1-EXECUTE SRCHIMAG"CRLF);
       OUTSTR("2-CHANGE MODES"CRLF);
  TES: OUTSTR("...TYPE  NO. OF THE PROCEDUE TO TEST NOW="CRLF);
	REQUEST←CVD(INCHWL); 
	IF (REQUEST<0)∨(REQUEST>2) THEN BEGIN
	   OUTSTR("TESTIT-FAILED: ILLEGAL NO ("&CVS(REQUEST)&")"CRLF);
           GOTO TIT;                    END;
	CASE REQUEST OF BEGIN
        BEGIN ⊃ 0; OUTSTR("BKGR= 0 FOR ANY, 1 FOR LIGHT, -1 FOR DARK"CRLF);
	           OUTSTR("INT= 0 FOR NO, -1 FOR LIGHT, 1 FOR DARK"CRLF);
	           OUTSTR("SEARCH= N>0 SERACH FOR 1 FEAT. IN AREA OF DIM. N"CRLF);
	           OUTSTR("        0 LOOK FOR 1 FEAT. AND RECENTER"CRLF);
	           OUTSTR("        -10<-N<0 LOOK FOR N FEATS."CRLF);
	           OUTSTR("TOLER= -1 FOR NO MATCH, >0 FOR TOLERANCE"CRLF);
		   GOTO TES;						 END;
	BEGIN ⊃ 1; OUTSTR("TYPE THE VALUES OF THE PARAMETERS,"&
                                  " EACH FOLLOWED BY C.R:"&
	             		  " BKGR,INT,SEARCH,TOLER"CRLF);
		   BKGR←CVD(INCHWL); INT←CVD(INCHWL); SEARCH←CVD(INCHWL);
		   COD←INCHWL; TOLER←REALSCAN(COD,DUMMY);
		   IF   (TOLER>0)∧(PERS=0)
		   THEN OUTSTR("TESTIT-FAILED: NO REFERENCE YET"CRLF)
	           ELSE SRCHIMAG(BKGR,INT,SEARCH,TOLER,DIRG); END;
	BEGIN ⊃ 2; OUTSTR("...TYPE Y TO CHANGE DEBUG MODE:"CRLF);
                   IF YES THEN DEB_EYE←¬DEB_EYE;
                   OUTSTR("...TYPE Y TO CHANGE DISPLAY MODE:"CRLF);
                   IF YES THEN DIS_EYE←¬DIS_EYE; GOTO TES;	END;
          			END;

	IF REQUEST=1 THEN BEGIN
    	   IF DIR_EYE[0,1]>1 THEN BEGIN
              OUTSTR("TESTIT: TYPE Y TO GENERATE REFERENCE:"CRLF);
	      IF YES THEN BEGIN
	         OUTSTR("TESTIT: TYPE NO. IN DIR_EYE="CRLF); INT←CVD(INCHWL);
	         IF   (INT>0)∧(INT<DIR_EYE[0,1]) 
                 THEN ARRBLT(DIRG[1],DIR_EYE[INT,1],8) 
	         ELSE OUTSTR("TESTIT-FAILED: ILLEGAL NO. "&CVS(INT)CRLF); END;
				  END;
           OUTSTR("TESTIT: TYPE VALUE OF DIRG[7]="CRLF);
           COD←INCHWL; DIRG[7]←REALSCAN(COD,DUMMY);
           OUTSTR("TESTIT: TYPE VALUE OF DIRG[8]="CRLF);
           COD←INCHWL; DIRG[8]←REALSCAN(COD,DUMMY); PERS←1; END;

       OUTSTR("...TYPE Y TO TEST AGAIN:"CRLF); 
      IF YES THEN GOTO TIT;
  END "TESTIT";

SIMPLE MESSAGE PROCEDURE SRCH_IMAGE(INTEGER BKGR,INT,SEARCH;
			     REAL TOLER; REAL ARRAY DIRD);
  BEGIN         ⊃ globals LOOK_AT and DIR_EYE are used as I/O;
    EXFLAG←0; DIR_EYE[0,1]←1;
    SRCHIMAG(BKGR,INT,SEARCH,TOLER,DIRD);
    EYEFLG←EXFLAG;
  END "SRCH_IMAGE";

SIMPLE MESSAGE PROCEDURE SET_WINDOW;
  BEGIN
    EXFLAG←0;
    SETWINDOW;
    EYEFLG←EXFLAG;
  END"SET_WINDOW";


    ⊃ Main Program;

    TVWORD←GIOWD(TVBUF); INTPNT;
    DIS_EYE←TRUE; DEB_EYE←FALSE;
    IF RUN=0 
    THEN  TESTIT
    ELSE BEGIN
 	  PUT_DATA(0,0,"EYE");        ⊃ DECLARE YOUR NAME ;
	  OUTSTR("EYE-ACTIVATED"CRLF);
	  YES_EYE←TRUE ;
 	  WHILE TRUE DO BEGIN
	    MESS ← GET_ENTRY ('120,NULL,"EYE",NULL);
	    MESS ← QUEUE ('600,MESS); ⊃ ACTIVATE AND ACKNOWLEDGE ;
 	  END; END;
END "GILEYE";